/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.springblade.modules.rate.event.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.swagger.models.auth.In;
import org.springblade.common.enums.rate.*;
import org.springblade.common.utils.CommonUtil;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.secure.BladeUser;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.modules.rate.event.entity.Event;
import org.springblade.modules.rate.event.entity.EventLike;
import org.springblade.modules.rate.event.mapper.EventLikeMapper;
import org.springblade.modules.rate.event.service.IEventLikeService;
import org.springblade.modules.rate.event.vo.EventVO;
import org.springblade.modules.rate.event.mapper.EventMapper;
import org.springblade.modules.rate.event.service.IEventService;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.modules.rate.event.vo.audit.EventAuditOperationVO;
import org.springblade.modules.rate.event.vo.audit.EventAuditReqVO;
import org.springblade.modules.rate.event.vo.detail.EventDetailVO;
import org.springblade.modules.rate.event.vo.detail.EventNoticeVO;
import org.springblade.modules.rate.event.vo.dismiss.EventDismissVO;
import org.springblade.modules.rate.event.vo.like.EventLikeOperationVO;
import org.springblade.modules.rate.point.entity.PointRecord;
import org.springblade.modules.rate.point.service.IPointRecordService;
import org.springblade.modules.system.entity.Dept;
import org.springblade.modules.system.entity.Tenant;
import org.springblade.modules.system.entity.User;
import org.springblade.modules.system.service.IDeptService;
import org.springblade.modules.system.service.ITenantService;
import org.springblade.modules.system.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springframework.transaction.annotation.Transactional;

import java.time.Duration;
import java.util.Date;
import java.util.List;

import static java.lang.Math.abs;

/**
 * 事件表 服务实现类
 *
 * @author Blade
 * @since 2021-09-20
 * <p>
 * <p>
 * /**
 * * 记得加分逻辑是这样的，可查看导图
 * * 1. 优秀事件只要审核通过，该事件相对应的员工就可得+5分自我表现分
 * * 2. 同一个事件有加分期限只有5天，超过5天谁都加不了分
 * * 3. 同一个事件每一位同事/领导最多只可以加五次分，一次1分或者可以询问提示加几分（看你们哪样容易做，即同事或领导觉得这件事确实很好，可以最高加到5分的意思）
 * * 4. 领导给员工事件的加分会消耗领导当月的额度
 * * 5. 批评事件的解锁分会消耗员工的自我表现分
 * * 6. 不需要取消加分（即取消点赞那种），加分了就是认可这个事
 */
@Service
public class EventServiceImpl extends BaseServiceImpl<EventMapper, Event> implements IEventService {

	@Autowired
	private IEventLikeService eventLikeService;
	@Autowired
	private EventLikeMapper eventLikeMapper;
	@Autowired
	private IPointRecordService pointRecordService;
	@Autowired
	private ITenantService tenantService;
	@Autowired
	private IUserService userService;
	@Autowired
	private IDeptService deptService;


	public IPage<Event> getEventPage(IPage<Event> page, EventVO eventVO) {
		Event event = new Event();
		if (eventVO.getAuditStatus() == null) {
			eventVO.setAuditStatus(AuditStatusEnum.DONE.getKey());
		}
		BeanUtil.copyNonNull(eventVO, event);
		IPage<Event> pages = this.page(page, Condition.getQueryWrapper(event));
		List<Event> eventVOList = pages.getRecords();
		if (eventVOList.size() == 0) {
			return page.setRecords(eventVOList);
		}

		List<EventLike> eventLikeList = eventLikeMapper.getEventLikeList(eventVOList, DateUtil.today());
		for (int i = 0; i < eventVOList.size(); i++) {
			Event event1 = eventVOList.get(i);
			for (int j = 0; j < eventLikeList.size(); j++) {
				EventLike eventLike = eventLikeList.get(j);
				if (eventLike.getEventCode().equals(eventVO.getCode())) {
					event1.setLikeFlag(1);
					eventVOList.set(i, event1);
					break;
				}
			}
		}
		return page.setRecords(eventVOList);
	}

	@Override
	public IPage<EventVO> selectEventPage(IPage<EventVO> page, EventVO event) {

		List<EventVO> eventVOList = baseMapper.selectEventPage(page, event);
		return page.setRecords(eventVOList);
	}

	/**
	 * 获取部门下的未审核事件
	 */
	@Override
	public IPage<Event> getCommitEvent(IPage<Event> page, BladeUser bladeUser) {
		boolean leaderFlag = false;
		BladeUser authUser = AuthUtil.getUser();
		User user = userService.getById(authUser.getUserId());
		if (user.getLeaderFlag() == YesNoEnum.YES.getKey()) {
			leaderFlag = true;
		}
		Event eventQ = new Event();
		eventQ.setCreateUser(user.getId());
		QueryWrapper<Event> queryWrapperQ = Condition.getQueryWrapper(eventQ);
		queryWrapperQ.apply("audit_status!=1");
		List<Event> items = this.list(queryWrapperQ);
		return page.setRecords(items);

	}

	@Override
	public IPage<Event> getUnAuditEvvent(IPage<Event> page, EventAuditReqVO auditReqVO) {
		boolean leaderFlag = false;
		BladeUser authUser = AuthUtil.getUser();
		User user = userService.getById(authUser.getUserId());
		if (user.getLeaderFlag() == YesNoEnum.YES.getKey()) {
			leaderFlag = true;
		}
		if (!leaderFlag) {
			return null;
		}
		Event auditEvent = new Event();
		auditEvent.setDeptId(user.getDeptId());
		auditEvent.setType(EventTypeEnum.GOOD.getKey());
		auditEvent.setAuditStatus(AuditStatusEnum.NO_AUDIT.getKey());
		BeanUtil.copyNonNull(auditReqVO, auditEvent);
		QueryWrapper<Event> queryWrapperQ = Condition.getQueryWrapper(auditEvent);
		if (auditReqVO.getStartDate() != null) {
			queryWrapperQ.apply("date_format (create_time,'%Y-%m-%d') >= " + auditReqVO.getStartDate());
		}
		if (auditReqVO.getEndDate() != null) {
			queryWrapperQ.apply("date_format (create_time,'%Y-%m-%d') <= " + auditReqVO.getEndDate());
		}
		List<Event> items = this.list(queryWrapperQ);
		return page.setRecords(items);
	}

	/**
	 * 发布操作
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean publish(EventVO eventVO) {
		try {
			boolean leaderFlag = false;
			BladeUser authUser = AuthUtil.getUser();
			User user = userService.getById(authUser.getUserId());
			if (user.getLeaderFlag() == YesNoEnum.YES.getKey()) {
				leaderFlag = true;
			}
			String code = "EVENT" + CommonUtil.getTimeString();
			eventVO.setCode(code);
			if (eventVO.getMedias() != null) {
				String[] mediaUrls = eventVO.getMedias().split(",");
				if (mediaUrls.length > 0) {
					eventVO.setMediaUrl(mediaUrls[0]);
				}
			}

			if (eventVO.getType() != null && eventVO.getType().equals(EventTypeEnum.BAD.getKey())) {
				if (!leaderFlag) {
					throw new ServiceException("角色无权限操作");
				}
				//批评事件
				if (eventVO.getPoint() != null) eventVO.setPoint(abs(eventVO.getPoint()));
				eventVO.setLockStatus(YesNoEnum.YES.getKey());
				eventVO.setAuditStatus(AuditStatusEnum.DONE.getKey());
				//员工状态 用户额度更新
				User exchangeUser = userService.getById(eventVO.getMemberId());
				exchangeUser.setStatus(UserStatusEnum.LOCK.getKey());
				exchangeUser.setQuota(exchangeUser.getQuota() - eventVO.getPoint());
				exchangeUser.setMouthQuota(exchangeUser.getMouthQuota() - eventVO.getPoint());
				userService.updateById(exchangeUser);
			}
			//部门员工名称
			User member = userService.getById(eventVO.getMemberId());
			eventVO.setMemberName(member.getRealName());
			if (StringUtil.isBlank(eventVO.getDeptId())) {
				eventVO.setDeptId(member.getDeptId());
			}
			Dept dept = deptService.getById(eventVO.getDeptId());
			eventVO.setDeptName(dept.getDeptName());
			this.saveOrUpdate(eventVO);

		} catch (Exception e) {
			log.error(e.getMessage());
			throw new ServiceException(e.getMessage());
		}
		return true;
	}

	/**
	 * 审核操作
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean audit(EventAuditOperationVO auditOperationVO) {
		try {

			boolean leaderFlag = false;
			BladeUser authUser = AuthUtil.getUser();
			User user = userService.getById(authUser.getUserId());
			if (user.getLeaderFlag() == YesNoEnum.YES.getKey()) {
				leaderFlag = true;
			}
			if (!leaderFlag) {
				throw new ServiceException("用户不是领导，不能审核");
			}
			//事件更新
			Event eventQ = new Event();
			eventQ.setCode(auditOperationVO.getEventCode());
			QueryWrapper<Event> queryWrapper = Condition.getQueryWrapper(eventQ).last("limit 1");
			Event event = this.getOne(queryWrapper);
			event.setContent(auditOperationVO.getContent());
			event.setAuditStatus(auditOperationVO.getOperation());
			this.saveOrUpdate(event);
			//审核通过
			if (auditOperationVO.getOperation().equals(1)) {
				User operationUser = userService.getById(user.getId());
				Tenant tenant = tenantService.getByTenantId(operationUser.getTenantId());
				//分数判断
				Integer point = tenant.getGoodEventPoint() != null ? tenant.getGoodEventPoint() : PointTypeEnum.SELF.getPoint();
				//用户额度更新
				//目标员工
				User exchangeUser = userService.getById(event.getMemberId());
				exchangeUser.setSelfPoint(exchangeUser.getSelfPoint() + point);
				userService.updateById(exchangeUser);
				//积分操作
				PointRecord pointRecord = new PointRecord();
				pointRecord.setName(PointTypeEnum.SELF.getKeyword());
				pointRecord.setType(PointTypeEnum.SELF.getKey());
				pointRecord.setPoint(point);
				pointRecord.setPickMemberId(user.getId());
				pointRecord.setPickMemberName(user.getRealName());
				pointRecord.setMemberId(exchangeUser.getId());
				pointRecord.setMemberName(exchangeUser.getRealName());
				pointRecord.setEventCode(auditOperationVO.getEventCode());
				pointRecordService.save(pointRecord);
			}


		} catch (Exception e) {
			log.error(e.getMessage());
			throw new ServiceException(e.getMessage());
		}
		return true;
	}

	/**
	 * 加分操作
	 *
	 * @param likeOperationVO
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean pickLike(EventLikeOperationVO likeOperationVO) {
		try {


			boolean leaderFlag = false;
			BladeUser authUser = AuthUtil.getUser();
			User user = userService.getById(authUser.getUserId());
			if (user.getLeaderFlag() == YesNoEnum.YES.getKey()) {
				leaderFlag = true;
			}
			if (user.getStatus().equals(UserStatusEnum.LOCK.getKey())) {
				throw new ServiceException("用户处于封锁状态，不能操作");
			}

			Tenant tenant = tenantService.getByTenantId(user.getTenantId());
			//分数判断
			Integer point = tenant.getMateLikePoint() != null ? tenant.getMateLikePoint() : PointTypeEnum.MATE.getPoint();
			if (leaderFlag) {
				point = tenant.getLeaderLikePoint() != null ? tenant.getLeaderLikePoint() : PointTypeEnum.LEADER.getPoint();
			}
			//事件
			Event eventQ = new Event();
			eventQ.setCode(likeOperationVO.getEventCode());
			QueryWrapper<Event> queryWrapper = Condition.getQueryWrapper(eventQ).last("limit 1");
			Event event = this.getOne(queryWrapper);
			if (user.getId().equals(event.getMemberId())) {
				throw new ServiceException("自己不能为自己加分");
			}
			if (!event.getAuditStatus().equals(AuditStatusEnum.DONE.getKey())) {
				throw new ServiceException("审核不通过，不能操作");
			}
			//事件的分数
			//点赞&取消点赞
			if (likeOperationVO.getOperation().equals(YesNoEnum.NO.getKey())) {
				point = -point;
			}
			if (likeOperationVO.getOperation().equals(YesNoEnum.YES.getKey())) {
				if (leaderFlag) {
					event.setLeaderLike(event.getLeaderLike() + 1);
				} else {
					event.setMateLike(event.getMateLike() + 1);
				}
			} else {
				if (leaderFlag) {
					event.setLeaderLike(event.getLeaderLike() - 1);
				} else {
					event.setMateLike(event.getMateLike() - 1);
				}
			}

			this.saveOrUpdate(event);

			//用户额度更新

			//目标员工
			User exchangeUser = userService.getById(event.getMemberId());
			if (leaderFlag) {
				exchangeUser.setLeaderPoint(exchangeUser.getLeaderPoint() + point);
			} else {
				exchangeUser.setMatePoint(exchangeUser.getMatePoint() + point);
			}
			userService.updateById(exchangeUser);
			//点赞员工
			User pickUser = userService.getById(user.getId());
			pickUser.setQuota(pickUser.getQuota() - point);
			pickUser.setMouthQuota(pickUser.getMouthQuota() - point);
			if (pickUser.getMouthQuota() < 0) {
				throw new ServiceException("当月额度不够");
			}
			userService.updateById(pickUser);

			//点赞关系表
			String todayDate = DateUtil.today();
			EventLike eventLikeQ = new EventLike();
			eventLikeQ.setPickMemberId(user.getId());
			eventLikeQ.setMemberId(exchangeUser.getId());
			eventLikeQ.setEventCode(likeOperationVO.getEventCode());
			eventLikeQ.setLikeDate(todayDate);
			EventLike oneEventLike = eventLikeService.getOne(Condition.getQueryWrapper(eventLikeQ).last("limit 1"));
			//1.点赞&取消点赞
			if (likeOperationVO.getOperation().equals(YesNoEnum.YES.getKey())) {
				EventLike eventLike = new EventLike();
				eventLike.setMemberType(leaderFlag ? 1 : 0);//领导还是一线员工
				eventLike.setPoint(point);
				eventLike.setPickMemberId(user.getId());
				eventLike.setMemberId(exchangeUser.getId());
				eventLike.setEventCode(likeOperationVO.getEventCode());
				eventLike.setLikeDate(todayDate);

				//2.同一天不能再点赞
				if (oneEventLike != null) {
					throw new ServiceException("每天只可加分一次");
				}
				//3.只有5天接受被加分
				Duration duration = DateUtil.between(event.getCreateTime(), new Date());
				if (duration.toDays() >= 5) {
					throw new ServiceException("只有5天接受被加分");
				}
				eventLikeService.save(eventLike);
			} else {
				//4.取消点赞
				eventLikeService.remove(Condition.getQueryWrapper(eventLikeQ));
			}

			//积分操作
			PointRecord pointRecord = new PointRecord();
			pointRecord.setType(leaderFlag ? PointTypeEnum.LEADER.getKey() : PointTypeEnum.MATE.getKey());//领导还是一线员工
			pointRecord.setName(PointTypeEnum.getEnum(pointRecord.getType()).getKeyword());
			pointRecord.setPoint(point);
			pointRecord.setPickMemberId(user.getId());
			pointRecord.setPickMemberName(user.getRealName());
			pointRecord.setMemberId(exchangeUser.getId());
			pointRecord.setMemberName(exchangeUser.getRealName());
			pointRecord.setEventCode(likeOperationVO.getEventCode());
			pointRecordService.save(pointRecord);


		} catch (Exception e) {
			log.error(e.getMessage());
			throw new ServiceException(e.getMessage());
		}
		return true;
	}

	/**
	 * 解封
	 *
	 * @param dismissVO
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean dismiss(EventDismissVO dismissVO) {
		try {

			boolean leaderFlag = false;
			BladeUser authUser = AuthUtil.getUser();
			User user = userService.getById(authUser.getUserId());
			if (user.getLeaderFlag() == YesNoEnum.YES.getKey()) {
				leaderFlag = true;
			}

			Event eventQ = new Event();
			eventQ.setCode(dismissVO.getEventCode());
			QueryWrapper<Event> queryWrapper = Condition.getQueryWrapper(eventQ).last("limit 1");
			Event event = this.getOne(queryWrapper);
			event.setLockStatus(YesNoEnum.NO.getKey());
			this.saveOrUpdate(event);
			//分数
			Integer point = -event.getPoint();
			//目标员工
			User exchangeUser = userService.getById(event.getMemberId());

			Event eventBad = new Event();
			eventBad.setLockStatus(YesNoEnum.YES.getKey());
			eventBad.setMemberId(exchangeUser.getId());
			QueryWrapper<Event> eventBadQ = Condition.getQueryWrapper(eventBad).last("limit 1");
			Event badEvent = this.getOne(eventBadQ);
			if (badEvent == null) {
				//没有批评事件可以解封
				exchangeUser.setStatus(UserStatusEnum.NORMAL.getKey());//用户状态
				userService.updateById(exchangeUser);
			}

			//解除员工
			User pickUser = userService.getById(user.getId());
			pickUser.setSelfPoint(pickUser.getSelfPoint() + point);
			if (pickUser.getSelfPoint() < 0) {
				if (pickUser.getId().equals(event.getMemberId())) {
					throw new ServiceException("自我解封失败，自我表现分不够");
				}
				throw new ServiceException("帮ta解封失败，自我表现分不够");
			}
			userService.updateById(pickUser);

			//积分操作
			PointRecord pointRecord = new PointRecord();
			pointRecord.setName(PointTypeEnum.DISMISS.getKeyword());
			pointRecord.setType(PointTypeEnum.DISMISS.getKey());//解封
			pointRecord.setPoint(point);
			pointRecord.setPickMemberId(user.getId());
			pointRecord.setPickMemberName(user.getRealName());
			pointRecord.setMemberId(user.getId());
			pointRecord.setMemberName(user.getRealName());
			pointRecord.setEventCode(event.getCode());
			pointRecordService.save(pointRecord);


		} catch (Exception e) {
			log.error(e.getMessage());
			throw new ServiceException(e.getMessage());
		}
		return true;
	}

	/**
	 * 详情
	 *
	 * @param event
	 */
	@Override
	public EventDetailVO getDetail(Event event) {
		EventDetailVO detailVO = new EventDetailVO();
		//获取详情
		Event detail = this.getOne(Condition.getQueryWrapper(event).last("limit 1"));
		detailVO.setDetail(detail);
		//判断是否点赞
		User user = userService.getById(AuthUtil.getUser().getUserId());
		EventLike eventLikeSelf = new EventLike();
		eventLikeSelf.setEventCode(detail.getCode());
		eventLikeSelf.setMemberId(user.getId());
		EventLike selfLike = eventLikeService.getOne(Condition.getQueryWrapper(eventLikeSelf).last("limit 1"));
		if (selfLike != null) {
			detail.setLikeFlag(1);
		}
		//获取同事表扬
		EventLike eventLike = new EventLike();
		eventLike.setEventCode(detail.getCode());
		eventLike.setMemberType(0);
		List<User> mateList = eventLikeMapper.getLikeMemberList(eventLike);
		detailVO.setMateList(mateList);
		//获取领导表扬
		EventLike eventLikeLeader = new EventLike();
		eventLikeLeader.setEventCode(detail.getCode());
		eventLikeLeader.setMemberType(1);
		List<User> leaderList = eventLikeMapper.getLikeMemberList(eventLikeLeader);
		detailVO.setLeaderList(leaderList);

		return detailVO;
	}

	/**
	 * 获取时间通知相关数字
	 */
	@Override
	public EventNoticeVO getEventNotice() {
		boolean leaderFlag = false;
		BladeUser authUser = AuthUtil.getUser();
		User user = userService.getById(authUser.getUserId());
		if (user.getLeaderFlag() == YesNoEnum.YES.getKey()) {
			leaderFlag = true;
		}

		EventNoticeVO noticeVO = new EventNoticeVO();
		Event eventQ = new Event();
		eventQ.setAuditStatus(AuditStatusEnum.NO_AUDIT.getKey());
		eventQ.setCreateUser(user.getId());
		QueryWrapper<Event> queryWrapper = Condition.getQueryWrapper(eventQ);
		Integer commitNumber = this.count(queryWrapper);
		noticeVO.setCommitNumber(commitNumber);

		Event eventQ1 = new Event();
		eventQ1.setDeptId(user.getDeptId());
		eventQ1.setAuditStatus(AuditStatusEnum.NO_AUDIT.getKey());
		QueryWrapper<Event> queryWrapper1 = Condition.getQueryWrapper(eventQ1);
		Integer unAuditNumber = this.count(queryWrapper1);
		noticeVO.setUnAuditNumber(unAuditNumber);

		return noticeVO;
	}
}
